#include <time.h>

#include "bsp_clock.h"
#include "drv_rtc.h"

/* static var */

static const char *tm_wday_tbl[7] = 
{
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

static const char *tm_month_tbl[12] = 
{
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

static char tm_buf[32];
static struct tm lib_tm;


/* export func */

/**
 * @brief 返回一个指向字符串的指针，它代表了结构 timeptr 的日期和时间。
 * 
 * @param timeptr 
 * @return char* 
 */
char *asctime(const struct tm *timeptr)
{
    memset(tm_buf, 0x00, sizeof(tm_buf));

    siprintf(tm_buf, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
             tm_wday_tbl[timeptr->tm_wday],
             tm_month_tbl[timeptr->tm_mon],
             timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min,
             timeptr->tm_sec, 1900 + timeptr->tm_year);

    return tm_buf;
}

/**
 * @brief 返回程序执行起（一般为程序的开头），处理器时钟所使用的时间，这里返回系统滴答时钟。
 * 
 * @return clock_t 
 */
clock_t clock(void)
{
    clock_t t;

    t = HAL_GetTick();
    return t;
}

/**
 * @brief 返回一个表示当地时间的字符串，当地时间是基于参数 timer。
 * 
 * @param timer 
 * @return char* 
 */
char *ctime(const time_t *timer)
{
    return asctime(localtime(timer));
}


/**
 * @brief 返回 time1 和 time2 之间相差的秒数 (time1-time2)。
 * 
 * @param time1 
 * @param time2 
 * @return double 
 */
double difftime(time_t time1, time_t time2)
{
    return (double)(time1 - time2);
}

/**
 * @brief timer 的值被分解为 tm 结构，并用协调世界时（UTC）也被称为格林尼治标准时间（GMT）表示。
 * 
 * @param timer 
 * @return struct tm* 
 */
struct tm *gmtime(const time_t *timer)
{
    _drv_rtc_time_t rtc;
    uint32_t unix;

    if (timer == NULL)
    {
        /* get local time */
        drv_rtc_lock();
        drv_rtc_get(&rtc);
        drv_rtc_unlock();
    }
    else
    {
        unix = *timer;
        drv_rtc_get_time_form_unix(&rtc, unix);
    }

    lib_tm.tm_sec = rtc.sec;
    lib_tm.tm_min = rtc.min;
    lib_tm.tm_hour = rtc.hour;
    lib_tm.tm_mday = rtc.date;
    lib_tm.tm_mon = rtc.month;
    lib_tm.tm_year = rtc.year - 1900;
    lib_tm.tm_wday = rtc.day;
    lib_tm.tm_yday = rtc.yday;

    return &lib_tm;
}

/**
 * @brief timer 的值被分解为 tm 结构，并用本地时区表示。
 * 
 * @param timer 
 * @return struct tm* 
 */
struct tm *localtime(const time_t *timer)
{
    return gmtime(timer);
}

/**
 * @brief 把 timeptr 所指向的结构转换为一个依据本地时区的 time_t 值。
 * 
 * @param timeptr 
 * @return time_t 
 */
time_t mktime(struct tm *timeptr)
{
    uint32_t unix;
    uint8_t ret;
    _drv_rtc_time_t rtc;

    if (timeptr == NULL) return -1;

    rtc.year = timeptr->tm_year + 1900;
    rtc.month = timeptr->tm_mon;
    rtc.date = timeptr->tm_mday;
    rtc.hour = timeptr->tm_hour;
    rtc.min = timeptr->tm_min;
    rtc.sec = timeptr->tm_sec;
    rtc.day = timeptr->tm_wday;
    rtc.yday = timeptr->tm_yday;

    ret = drv_rtc_get_unix_form_time(&rtc, &unix);
    if (ret) return -1;

    return unix;
}

/**
 * @brief 根据 format 中定义的格式化规则，格式化结构 timeptr 表示的时间，并把它存储在 str 中。
 * 
 * @param str 
 * @param maxsize 
 * @param format 
 * @param timeptr 
 * @return size_t 
 */
// size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
// {
// }

/**
 * @brief 计算当前日历时间，并把它编码成 time_t 格式。
 * 
 * @param seconds 
 * @return time_t 
 */
time_t time(time_t *seconds)
{
    time_t tm;
    _drv_rtc_time_t rtc;
    uint32_t unix = 0;
    uint8_t ret;

    /* get local time */
    drv_rtc_lock();
    drv_rtc_get(&rtc);
    drv_rtc_unlock();

    /* calculate unix */
    ret = drv_rtc_get_unix_form_time(&rtc, &unix);
    if (ret) unix = 0;

    if (seconds != NULL)
    {
        *seconds = unix;
    }
    tm = (time_t)unix;

    return tm;
}




















